#include "memory_pool.h"
#include <stdlib.h>
#include <stdio.h>

struct memory_pool_t *memory_pool_create(int data_size, int object_count){
	struct memory_pool_t *pool = (struct memory_pool_t *)malloc(sizeof(struct memory_pool_t));
	pool->data_size = data_size;
	pool->object_count = object_count;
    list_init(&pool->free_node_head);
    list_init(&pool->mem_block_head);
    return pool;
}

void memory_pool_destroy(struct memory_pool_t *pool){
    if(pool == NULL) return;
    struct mem_block_t *p,*tmp;
    list_for_each_entry_safe(p, tmp, &pool->mem_block_head, entry) {
        list_del(&p->entry);
        free(p->nodes);
        free(p);
    }
    list_del_init(&pool->free_node_head);
    list_del_init(&pool->mem_block_head);
    free(pool);
}

void* memory_pool_malloc(struct memory_pool_t *pool) {
    //无空闲节点，申请新内存块
    if (list_empty(&pool->free_node_head)) {
        struct mem_block_t *newBlock = (struct mem_block_t *)malloc(sizeof(struct mem_block_t));
        int node_size  = sizeof(struct free_node_t) +  pool->data_size - sizeof(char *);
        newBlock->nodes = (struct free_node_t *)malloc(node_size * pool->object_count);
        // 将内存块的其它节点串起来
        for (int i = 0; i < pool->object_count; ++i) {
            struct free_node_t * node = (struct free_node_t *)((char *)newBlock->nodes + node_size*i);
            list_add_tail(&node->entry, &pool->free_node_head);
        }
        // 将新内存块加入到内存块链表。
        list_add_tail(&newBlock->entry, &pool->mem_block_head);
    }

    struct free_node_t *node = list_first_entry_or_null(&pool->free_node_head, struct free_node_t, entry);
    list_del(&node->entry);
    return node;
}

void  memory_pool_free(struct memory_pool_t *pool, void *node) {
    list_add(&((struct free_node_t *)node)->entry, &pool->free_node_head);
}